/*******************************************************************************
 * Copyright 2011 Towee.net
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package net.towee.client.managers;

import java.util.List;

import net.towee.client.event.core.GroupCreatedEvent;
import net.towee.client.event.core.GroupUpdatedEvent;
import net.towee.client.event.core.UserEnteredToGroupEvent;
import net.towee.client.event.core.UserLeaveFromGroupEvent;
import net.towee.model.account.AccountGroup;
import net.towee.model.account.AccountIdentity;
import net.towee.model.group.GroupData;
import net.towee.model.group.GroupEnterRequest;
import net.towee.model.group.GroupProfile;
import net.towee.model.utils.Pair;

import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * This manager work with GroupData. It can get, search and put group data to
 * server
 * 
 * <ul>The implementation MUST handle this PUSH events:
 * <li>User leaved from group - {@link UserLeaveFromGroupEvent}</li>
 * <li>User entered to group - {@link UserEnteredToGroupEvent}</li>
 * </ul>
 * 
 * @author viiv.c58@gmail.com (Artem Artem'ev)
 */
public interface GroupsManager {

	/**
	 * Get single group data with id. Current logged in user MUST have
	 * permission to get testAnswer or enterRequests. If user not have any of
	 * this permissions this method return GroupData without fields.
	 * 
	 * @param id
	 * @param handler
	 */
	public void getGroupData(String id, AsyncCallback<GroupData> handler);

	/**
	 * Get groups that contain in name or in alias some keywords from
	 * given string
	 * 
	 * @param start
	 * @param groupsPerPage
	 * @param tags
	 * @param type
	 * @param handler
	 */
	public void findGroup(String str, int offset, int limit, AsyncCallback<List<GroupProfile>> handler);
	
	/**
	 * Get list of users in group with given id in given range.
	 * 
	 * @param groupId
	 * @param asyncCallback
	 */
	public void getGroupMembers(String groupId, int offset, int limit, AsyncCallback<List<Pair<AccountIdentity, AccountGroup>>> asyncCallback);
	
	/**
	 * Get list of online users in group with given id and given range. 
	 * 
	 * @param groupId
	 * @param offset
	 * @param limit
	 * @param handler
	 */
	public void whosOnline(String groupId, int offset, int limit, AsyncCallback<List<AccountIdentity>> handler);

	/**
	 * Get groups by list of ids. User must be entered to all of groups with given IDs. 
	 * 
	 * @param start
	 * @param groupsPerPage
	 * @param set
	 * @param handler
	 */
	public void getGroupsByIds(List<String> set, AsyncCallback<List<GroupProfile>> handler);

	/**
	 * Add new request for entering to group. Group with given id MUST be a
	 * group with openness WITH_REQUEST. Otherwise it do nothing.
	 * 
	 * If test question is wrong it invoke onFailure with PersistenceException exception.
	 * 
	 * @param groupId
	 * @param accountId
	 * @param testAnsw answer for test question
	 */
	public void addEnterRequest(String groupId, String accountId, String testAnsw, AsyncCallback<Boolean> handler);

	/**
	 * Process enter request for given account and group. Current logged in user
	 * MUST have permission to do this.
	 * 
	 * @param groupId
	 * @param accountId
	 */
	public void processEnterRequest(String groupId, String accountId, AsyncCallback<Boolean> handler);

	/**
	 * Get enter requests of given group. User must have permission to do it.
	 * 
	 * @param groupId
	 * @param offset TODO
	 * @param limit TODO
	 */
	public void getEnterRequests(String groupId, int offset, int limit, AsyncCallback<List<GroupEnterRequest>> handler);

	/**
	 * This method create new group. Given group MUST have: alias, printName,
	 * testQuest and openness.
	 * 
	 * It invoke success method with given group(group data contain new group id, generated
	 * from server)
	 * 
	 * When gorup created user enter to this group automatically, this method add
	 * new AccountGroup object to local stored account and fire an event 
	 * {@link GroupCreatedEvent} with given group and {@link UserEnteredToGroupEvent}
	 * with created AccountData object. 
	 * 
	 * @param group
	 * @param handler
	 */
	public void createGroup(GroupData group, AsyncCallback<GroupData> handler);

	/**
	 * Update group printing name.
	 * 
	 * On success it fire an event {@link GroupUpdatedEvent}
	 * 
	 * @param group
	 */
	public void updatePrintName(String groupId, String newName, AsyncCallback<Boolean> handler);
	
	/**
	 * Update group profile
	 * 
	 * On success it fire an event {@link GroupUpdatedEvent}
	 * 
	 * @param groupProfile
	 * @param handler
	 */
	public void updateProfile(GroupProfile groupProfile, AsyncCallback<Boolean> handler);
	
	/**
	 * Try enter to group with given id and answer to test question.
	 * On success it invoke handler method with created AccounGroup object and
	 * fire an event {@link UserEnteredToGroupEvent} with the same object.
	 * 
	 * @param groupId
	 * @param testAnswer
	 * @param handler
	 */
	public void enterToGroup(String groupId, String testAnswer, AsyncCallback<AccountGroup> handler);

	/**
	 * Leave group with given id. On success it invoke handler method and fire
	 * an event {@link UserLeaveFromGroupEvent}.
	 * 
	 * @param groupId
	 * @param handler
	 */
	public void leaveGroup(String groupId, AsyncCallback<Boolean> handler);
	
	/**
	 * Kick user from given group. Current logged in user must have permission in
	 * given group to do that.
	 * 
	 * @param groupId
	 * @param userId
	 * @param handler
	 */
	public void kickUserFromGroup(String groupId, String userId, AsyncCallback<Boolean> handler);
	
	/**
	 * Return question for given group
	 * 
	 * @param groupId
	 * @param handler
	 */
	public void getGroupQuestion(String groupId, AsyncCallback<String> handler);

	/**
	 * Get answer for the question
	 * @param id
	 * @param asyncCallback
	 */
	public void getGroupQuestionAnswer(String id, AsyncCallback<String> asyncCallback);

	public void updateGroupQuestAnswer(String id, String quest, String questAnswer,
			AsyncCallback<Boolean> asyncCallback);

	public void getAllGroups(int offset, int limit, AsyncCallback<List<GroupProfile>> asyncCallback);
}
